#coding:utf-8

import Config;
import wx;
import os;
import wx.lib.rcsizer as rcs;
import wx.lib.intctrl;
import Global;
import Loading;
import string;
import ELog;
import traceback;
import array;
import time;
import numpy;  
import matplotlib;
import matplotlib.figure;
import matplotlib.backends.backend_wxagg;
import matplotlib.backends.backend_wx;

try:
    from agw import fourwaysplitter as FWS
except ImportError: # if it's not there locally, try the wxPython lib.
    try:
        import wx.lib.agw.fourwaysplitter as FWS
    except ImportError:
        exit()

#菜单ID
from AppIds import *

import SerialUtil
import wx.lib.newevent

#Frame start
SERIAL_GENIUS_FS_CHAR=0x0F;
#Slash
SERIAL_GENIUS_SL_CHAR=0x1F;



#变量助手列表
class PanelModuleVariableList(wx.ListCtrl):
    
    def __init__(self, parent):
        wx.ListCtrl.__init__(
            self, parent, -1, 
            style=wx.LC_REPORT|wx.LC_VIRTUAL|wx.LC_HRULES|wx.LC_VRULES
            )
        
        
        self.parent=parent;
        
        self.InsertColumn(0, u"编号");
        self.InsertColumn(1, "INT8U");
        self.InsertColumn(2, "INT8S");
        self.InsertColumn(3, "INT16U");
        self.InsertColumn(4, "INT16S");
        self.InsertColumn(5, "INT32U");
        self.InsertColumn(6, "INT32S");

        self.SetColumnWidth(0, 50);
        self.SetColumnWidth(1, 50);
        self.SetColumnWidth(2, 50);
        self.SetColumnWidth(3, 80);
        self.SetColumnWidth(4, 80);
        self.SetColumnWidth(5, 100);
        self.SetColumnWidth(6, 100);

        self.SetItemCount(256);
        
        self.refreshTimer = wx.Timer(self);
        self.Bind(wx.EVT_TIMER, self.RefreshData);
        self.refreshTimer.Start(1000);
        self.dataChanged=False;
    
    #刷新数据
    def RefreshData(self, event):
        if self.dataChanged:
            self.Refresh();
        self.dataChanged=False;
    
    #---------------------------------------------------
    # These methods are callbacks for implementing the
    # "virtualness" of the list...  Normally you would
    # determine the text, attributes and/or image based
    # on values from some external data source, but for
    # this demo we'll just calculate them
    def OnGetItemText(self, item, col):
        value=self.parent.Data[item][col-1];
        if self.parent.hexMode:
            if col==0:
                return ('0x%02X' % item);
            else:
                if col<=2:
                    if value>=0:
                        return ('0x%02X' % value);
                    else:
                        return ('0x%02X' % (value+0x100));
                elif col<=4:
                    if value>=0:
                        return ('0x%04X' % value);
                    else:
                        return ('0x%04X' % (value+0x10000));
                else:
                    if value>=0:
                        return ('0x%08X' % value);
                    else:
                        return ('0x%08X' % (value+0x100000000));
        else:
            if col==0:
                return item;
            else:
                return value;

    def OnGetItemImage(self, item):
        return -1

    def OnGetItemAttr(self, item):
        return None

#变量助手      
class Variable(wx.Panel):
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, style=wx.BORDER_DOUBLE);

        ############# 状态信息 ############
        #该模块是否启用
        self.isUsing=False;

        ############# 配置信息 ############
        #self.Data= [[0] * 6] * 256;
        self.Data=[[0 for col in range(7)] for row in range(256)];
        self.hexMode=False;
        self.dataBuffer=[];
        # 命令解析状态
        # 0 无
        # 1 INT8U
        # 2 INT8S
        # 3 INT16U
        # 4 INT16S
        # 5 INT32U
        # 6 INT32S
        self.dataParseCurStatus=0;
        self.dataparseCurLength=0;
        
        ############# 开始布局 ###########
        gridSizer = rcs.RowColSizer();
        
        rowTotal=3;
        colTotal=2;

        #标题
        title=wx.StaticText(self, -1, u"变量助手");
        title.SetFont(wx.Font(8, wx.FONTFAMILY_DEFAULT, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_BOLD ));
        gridSizer.Add(title, pos=(0,0), size=(1, colTotal), flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL);

        #变量显示区域
        self.listData = PanelModuleVariableList(self);        
        gridSizer.Add(self.listData, pos=(1,0), size=(1, colTotal), flag=wx.EXPAND);

        
        #清空
        btn = wx.Button(self, -1, u"清空")
        self.Bind(wx.EVT_BUTTON, self.OnClearData, btn);
        gridSizer.Add(btn, pos=(2, 0), size=(1,1), flag=wx.ALIGN_CENTER_VERTICAL);
        
        #显示模式
        ck=wx.CheckBox(self, -1, u"十六进制显示");
        ck.Bind(wx.EVT_CHECKBOX, self.OnHexMode);
        gridSizer.Add(ck, pos=(2, 1), size=(1,1), flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL);
        if Config.APP_CONFIG['module_variable']['hexMode']=='1':
            ck.SetValue(True);
            self.hexMode=True;

        #调试时候显示字符
        #self.debugText=wx.StaticText(self, -1, "");
        #gridSizer.Add(self.debugText, pos=(2,1), size=(1, colTotal), flag=wx.EXPAND|wx.ALIGN_CENTER_VERTICAL);

        #设置变宽信息
        gridSizer.AddGrowableCol(1);
        gridSizer.AddGrowableRow(1);


        ############# 结束布局 ###########
        self.SetSizer(gridSizer)
        self.SetAutoLayout(True)
    
    
    #获取数据部分中下一个数据（如果转义自动去除转义符号）
    def GetNextDataByte(self):
        if self.dataBuffer[0]==SERIAL_GENIUS_SL_CHAR:
            self.dataBuffer.pop(0);
        return self.dataBuffer.pop(0);           
    
    #新增串口数据，被串口接收所调用
    def RecvData(self, data):
        self.dataBuffer.extend(data);
        #解析数据
        while (self.dataParseCurStatus==0 and len(self.dataBuffer)>=5) or (self.dataParseCurStatus!=0 and len(self.dataBuffer)>=self.dataparseCurLength):
            try:
                if self.dataParseCurStatus==0:
                    
                    #找到帧头
                    while len(self.dataBuffer)>1:
                        if self.dataBuffer[0]==SERIAL_GENIUS_FS_CHAR:
                            break;
                        if self.dataBuffer[0]==SERIAL_GENIUS_SL_CHAR:
                            self.dataBuffer.pop(0);
                        self.dataBuffer.pop(0);
                    
                    if len(self.dataBuffer)<5:
                        break;
                    
                    # 0F 命令 长度 校验 数据...
                    
                    #无
                    if self.dataBuffer[0]==SERIAL_GENIUS_FS_CHAR:
                        if 0x01<=self.dataBuffer[1]<=0x06:
                        
                            if self.dataBuffer[3]==self.dataBuffer[1]^self.dataBuffer[2]:
                                self.dataParseCurStatus=self.dataBuffer[1];
                                self.dataparseCurLength=self.dataBuffer[2];
                                
                                self.dataBuffer.pop(0);
                                self.dataBuffer.pop(0);
                                self.dataBuffer.pop(0);
                                self.dataBuffer.pop(0);
                            else:
                                #数据校验出错
                                self.dataBuffer.pop(0);
                                self.dataBuffer.pop(0);
                                self.dataBuffer.pop(0);
                                self.dataBuffer.pop(0);
                        else:
                            #不是我们的数据
                            self.dataBuffer.pop(0);
                            self.dataBuffer.pop(0);
                            self.dataBuffer.pop(0);
                            self.dataBuffer.pop(0);
                    else:
                        #不是一个帧头，在这里忽略
                        self.dataBuffer.pop(0);                 
                            
                elif self.dataParseCurStatus==0x01:
                    self.dataParseCurStatus=0;
                    
                    #INT8U
                    item=self.GetNextDataByte();
                    value=self.GetNextDataByte();
                    
                    if 0<=item<=255:
                        self.Data[item][0]=value;
                        self.listData.dataChanged=True;
                    
                elif self.dataParseCurStatus==0x02:
                    self.dataParseCurStatus=0;
                    
                    #INT8S
                    item=self.GetNextDataByte();
                    value=self.GetNextDataByte();
                    if value>127:
                        value=value-0x100;
                    if 0<=item<=255:
                        self.Data[item][1]=value;
                        self.listData.dataChanged=True;
                
                elif self.dataParseCurStatus==0x03:
                    self.dataParseCurStatus=0;
                    
                    #INT16U
                    item=self.GetNextDataByte();
                    valueH=self.GetNextDataByte();
                    valueL=self.GetNextDataByte();
                    value=(valueH<<8)|valueL;
                    if 0<=item<=255:
                        self.Data[item][2]=value;
                        self.listData.dataChanged=True;
                
                elif self.dataParseCurStatus==0x04:
                    self.dataParseCurStatus=0;
                
                    #INT16S
                    item=self.GetNextDataByte();
                    valueH=self.GetNextDataByte();
                    valueL=self.GetNextDataByte();
                    value=(valueH<<8)|valueL;
                    if value>0x7FFF:
                        value=value-0x10000;
                    if 0<=item<=255:
                        self.Data[item][3]=value;
                        self.listData.dataChanged=True;
                
                elif self.dataParseCurStatus==0x05:
                    self.dataParseCurStatus=0;
                    
                    #INT32U
                    item=self.GetNextDataByte();
                    valueHH=self.GetNextDataByte();
                    valueHL=self.GetNextDataByte();
                    valueLH=self.GetNextDataByte();
                    valueLL=self.GetNextDataByte();
                    value=(valueHH<<24)|(valueHL<<16)|(valueLH<<8)|valueLL;
                    if 0<=item<=255:
                        self.Data[item][4]=value;
                        self.listData.dataChanged=True;
                
                elif self.dataParseCurStatus==0x06:
                    self.dataParseCurStatus=0;
                    
                    #INT32S
                    item=self.GetNextDataByte();
                    valueHH=self.GetNextDataByte();
                    valueHL=self.GetNextDataByte();
                    valueLH=self.GetNextDataByte();
                    valueLL=self.GetNextDataByte();
                    value=(valueHH<<24)|(valueHL<<16)|(valueLH<<8)|valueLL;
                    if value>0x7FFFFFFF:
                        value=value-0x100000000;
                    if 0<=item<=255:
                        self.Data[item][5]=value;
                        self.listData.dataChanged=True;
                                 
                else:
                    self.dataParseCurStatus=0;
                    
            except:
                self.dataParseCurStatus=0;
                break;
                
        #strs='';
        #for i in range(0,len(self.dataBuffer)):
        #    strs+=('%02X ' % self.dataBuffer[i]);    
        #self.debugText.SetLabel(strs);
        
    #十六进制显示模式
    def OnHexMode(self, event):
        self.hexMode=event.GetEventObject().GetValue();
        if self.hexMode:
            Config.APP_CONFIG['module_variable']['hexMode']='1';
        else:
            Config.APP_CONFIG['module_variable']['hexMode']='0';
        self.listData.Refresh();

    def OnClearData(self, event):
        for i in range(0,6):
            for j in range(0,256):
                self.Data[j][i]=0;
        self.listData.Refresh();
